using System;
using System.Collections;
using System.Xml;
using System.Runtime.InteropServices;

namespace ScenarioFramework.Modules.PCM.DataModel.ConfigurationManager.MetaWorkflow
{
	//*********************************************************************
	//
	// XMLMetaWorkflows Class
	//
	// The XMLMetaWorkflows class represents a collection base of XMLMetaWorkflow
	// Its imports methods from WAPI.XmlObjectSet like get set and add
	// XMLMetaWorkflows Has no fields
	//
	//*********************************************************************
	public class XMLMetaWorkflows : bOSdotNET.XML.Data.XMLObjectSet 
	{
		public const string MAIN_NODE = "MetaWorkflows";

		/** FIELDS **/

		/** no fields **/

		/** CONSTRUCTORS **/

		/** CONSTRUCTOR Empty **/
		public XMLMetaWorkflows()
		{
			this.Init();
		}

		/** CONSTRUCTOR Width xml parsering**/
		public XMLMetaWorkflows(System.Xml.XmlNode nodeList)
		{
			this.Parse (nodeList);
		}

		/** INSTANCE METHODS **/

		override public void Init()
		{
			this.RemoveAll();
		}

		override public void Parse(System.Xml.XmlNode nodeList)
		{
			this.Init();

			System.Xml.XmlNode node;

			for ( int i=0; i<nodeList.ChildNodes.Count;i++)
			{
				node = nodeList.ChildNodes[i];

				switch ( node.Name) 
				{
					case XMLMetaWorkflow.MAIN_NODE:
						this.Add ( new XMLMetaWorkflow(node));
						break;
				}
			}
		}

		override public bOSdotNET.XML.XMLNode GetXMLNode()
		{
			bOSdotNET.XML.XMLNode xmlNode = new bOSdotNET.XML.XMLNode(XMLMetaWorkflows.MAIN_NODE);

			for ( int i=0; i<this.Count;i++)
			{
				xmlNode.AddNode ( this[i].GetXMLNode() );
			}

			return xmlNode;
		}

		/** Method for return a metaworkflow from collection **/
		public XMLMetaWorkflow Get(string sMetaWorkflowName)
		{
			if ( this.List.Count != 0 )
			{
				for ( int i=0; i<this.List.Count;i++)
				{
					XMLMetaWorkflow mw = (XMLMetaWorkflow)this.List[i];

					if ( mw.Name == sMetaWorkflowName ) 
					{
						return mw;
					}
				}
			}

			ScenarioFramework.Modules.PCM.DataModel.ConfigurationManager.PCMWAPIResponse wapiResponse = new ScenarioFramework.Modules.PCM.DataModel.ConfigurationManager.PCMWAPIResponse();
			String sXML = XMLMetaWorkflows.GetMetaWorkflow (sMetaWorkflowName, ref wapiResponse);
			if ( wapiResponse.iCode != 0 )
			{
				throw new Exception.MetaWorkflowNotFound(sMetaWorkflowName + " not found.");
			}

			XMLMetaWorkflow xmlWF = new XMLMetaWorkflow();
			xmlWF.Parse (sXML);

			return xmlWF;
		}


		public XMLMetaWorkflow GetFile(string sMetaWorkflowName)
		{
			ScenarioFramework.Modules.PCM.DataModel.ConfigurationManager.PCMWAPIResponse wapiResponse = new ScenarioFramework.Modules.PCM.DataModel.ConfigurationManager.PCMWAPIResponse();
			String sXML = XMLMetaWorkflows.GetMetaWorkflow (sMetaWorkflowName, ref wapiResponse);
			if ( wapiResponse.iCode != 0 )
			{
				throw new Exception.MetaWorkflowNotFound(sMetaWorkflowName + " not found.");
			}

			XMLMetaWorkflow xmlWF = new XMLMetaWorkflow();
			xmlWF.Parse (sXML);

			return xmlWF;
		}

		/** Method for adding a metaworkflow in collection **/
		public void AddMetaWorkflow(XMLMetaWorkflow mw)
		{
			ScenarioFramework.Modules.PCM.DataModel.ConfigurationManager.PCMWAPIResponse response = new ScenarioFramework.Modules.PCM.DataModel.ConfigurationManager.PCMWAPIResponse();

			//Adding to Directory
			XMLMetaWorkflows.AddMetaWorkflow(mw.GetXML(), ref response);

			if ( response.iCode == 0 )
			{
				this.Add(mw);
			}
			else
			{
				throw new Exception.MetaWorkflowException(response.sMsg);
			}
		}

		/** Method for remove a metaworkflow from collection **/
		public void DeleteMetaWorkflow(XMLMetaWorkflow mw)
		{
			ScenarioFramework.Modules.PCM.DataModel.ConfigurationManager.PCMWAPIResponse response = new ScenarioFramework.Modules.PCM.DataModel.ConfigurationManager.PCMWAPIResponse();

			//Adding to Directory
			XMLMetaWorkflows.DeleteMetaWorkflow(mw.GetXML(), ref response);

			if ( response.iCode == 0 )
			{
				this.Remove(mw.Name);
			}
			else
			{
				throw new Exception.MetaWorkflowException(response.sMsg);
			}
		}

		/** Method for update a metaworkflow from collection **/
		public void UpdateMetaWorkflow(XMLMetaWorkflow mw)
		{
			ScenarioFramework.Modules.PCM.DataModel.ConfigurationManager.PCMWAPIResponse response = new ScenarioFramework.Modules.PCM.DataModel.ConfigurationManager.PCMWAPIResponse();

			//Adding to Directory
			XMLMetaWorkflows.UpdateMetaWorkflow(mw.GetXML(), ref response);

			if ( response.iCode == 0 )
			{
				if ( this.Remove(mw.Name) )
				{
					this.Add(mw);
				}
			}
			else
			{
				throw new Exception.MetaWorkflowException(response.sMsg);
			}
		}

		/** Method for filling the metaworkflows widthout calling WAPI first **/
		public void ReadFromConfiguration()
		{
			this.RemoveAll();
			ScenarioFramework.Modules.PCM.DataModel.ConfigurationManager.PCMWAPIResponse response = new ScenarioFramework.Modules.PCM.DataModel.ConfigurationManager.PCMWAPIResponse();
			String sMetaWorkflows = XMLMetaWorkflows.GetMetaWorkflows(ref response);

			if ( response.iCode == 0 )
			{
				this.Parse (sMetaWorkflows);
			}
			else
			{
				throw new Exception.ConfigurationError ( response.sMsg);
			}
		}

		private bool Remove(string sWorkflowName)
		{
			bool bRet = false;

			for ( int i=0; i<this.List.Count; i++)
			{
				XMLMetaWorkflow wf = (XMLMetaWorkflow) this.List[i];

				if ( wf.Name == sWorkflowName )
				{
					this.List.RemoveAt(i);
					return true;
				}
			}

			return bRet;

		}


		/** WAPI Wrappers to call SCENARIO ENGINE **/

		[ DllImport( "ConfigurationManager.dll", EntryPoint="GetMetaWorkflows")]
		public static extern string GetMetaWorkflows(ref ScenarioFramework.Modules.PCM.DataModel.ConfigurationManager.PCMWAPIResponse response);

		[ DllImport( "ConfigurationManager.dll", EntryPoint="AddMetaWorkflow")]
		public static extern string AddMetaWorkflow(string sMetaWorkflow, ref ScenarioFramework.Modules.PCM.DataModel.ConfigurationManager.PCMWAPIResponse response);

		[ DllImport( "ConfigurationManager.dll", EntryPoint="DeleteMetaWorkflow")]
		public static extern string DeleteMetaWorkflow(string sMetaWorkflow, ref ScenarioFramework.Modules.PCM.DataModel.ConfigurationManager.PCMWAPIResponse response);

		[ DllImport( "ConfigurationManager.dll", EntryPoint="UpdateMetaWorkflow")]
		public static extern string UpdateMetaWorkflow(string sMetaWorkflow, ref ScenarioFramework.Modules.PCM.DataModel.ConfigurationManager.PCMWAPIResponse response);

		[ DllImport( "ConfigurationManager.dll", EntryPoint="GetMetaWorkflow")]
		public static extern string GetMetaWorkflow(string sMetaWorkflow, ref ScenarioFramework.Modules.PCM.DataModel.ConfigurationManager.PCMWAPIResponse response);



		/** SORTING  FIELDS **/

		public enum SortFields 
		{
			Name,
			Description
		}

		/** SORTING METHODS **/


		public void Sort(SortFields sortField, bool isAscending) 
		{
			switch (sortField) 
			{
				case SortFields.Name:
					InnerList.Sort(new NameComparer());
					break;
				case SortFields.Description:
					InnerList.Sort(new DescriptionComparer());
					break;
				
			}
			if (!isAscending) InnerList.Reverse();
		}


		private sealed class NameComparer : IComparer 
		{
			public int Compare(object x, object y) 
			{
				XMLMetaWorkflow first = (XMLMetaWorkflow) x;
				XMLMetaWorkflow second = (XMLMetaWorkflow) y;
				return first.Name.CompareTo(second.Name);
			}
		}

		private sealed class DescriptionComparer : IComparer 
		{
			public int Compare(object x, object y) 
			{
				XMLMetaWorkflow first = (XMLMetaWorkflow) x;
				XMLMetaWorkflow second = (XMLMetaWorkflow) y;
				return first.Description.CompareTo(second.Description);
			}
		}
	}
}
